package com.qys.livesMall.shortVideo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.shortVideo.event.ShortVideoAddEvent;
import com.qys.livesMall.shortVideo.mapper.H2ShortVideoMapper;
import com.qys.livesMall.shortVideo.mapper.ShortVideoUserMapper;
import com.qys.livesMall.shortVideo.model.dto.ShortVideoEventDTO;
import com.qys.livesMall.shortVideo.model.dto.app.AppVideoUserDTO;
import com.qys.livesMall.shortVideo.model.entity.H2ShortVideo;
import com.qys.livesMall.shortVideo.model.entity.ShortVideoUser;
import com.qys.livesMall.shortVideo.model.enums.ShortVideoEventTypeEnum;
import com.qys.livesMall.shortVideo.model.vo.app.AppUserCollectionLikeVO;
import com.qys.livesMall.shortVideo.service.ShortVideoUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 * 短视频用户关联表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-05-29
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShortVideoUserServiceImpl extends ServiceImpl<ShortVideoUserMapper, ShortVideoUser> implements ShortVideoUserService {

    private final ApplicationContext applicationContext;
    private final H2ShortVideoMapper shortVideoMapper;

    /**
     * 创建用户短视频关联信息
     *
     * @param videoId                 短视频id
     * @param userId                  用户id
     * @param shortVideoEventTypeEnum {@link ShortVideoEventTypeEnum}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(String videoId, Long userId, ShortVideoEventTypeEnum shortVideoEventTypeEnum) {
        H2ShortVideo shortVideo = shortVideoMapper.selectById(videoId);
        if (null == shortVideo) {
            throw new QysException(MessageUtils.message("video.not.found"));
        }

        ShortVideoUser videoUser = new ShortVideoUser();
        videoUser.setUserId(userId);
        videoUser.setVideoId(Long.valueOf(videoId));

        videoUser.setImg(shortVideo.getImg());
        videoUser.setUrl(shortVideo.getUrl());
        videoUser.setDetail(shortVideo.getDetail());
        videoUser.setTitle(shortVideo.getTitle());

        switch (shortVideoEventTypeEnum) {
            //点赞
            case LIKE -> {
                videoUser.setLike((byte) 1);
                videoUser.setLikeTime(LocalDateTime.now());
            }
            //收藏
            case COLLECTION -> {
                videoUser.setCollection((byte) 1);
                videoUser.setCollectionTime(LocalDateTime.now());
            }
        }

        baseMapper.insert(videoUser);
    }

    /**
     * 用户点赞/取消点赞
     *
     * @param videoUser               {@link ShortVideoUser}
     * @param shortVideoEventTypeEnum {@link ShortVideoEventTypeEnum}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ShortVideoUser videoUser, ShortVideoEventTypeEnum shortVideoEventTypeEnum) {
        switch (shortVideoEventTypeEnum) {
            //点赞
            case LIKE -> {
                videoUser.setLike((byte) (1 == videoUser.getLike() ? 0 : 1));
                videoUser.setLikeTime(LocalDateTime.now());
            }
            //收藏
            case COLLECTION -> {
                videoUser.setCollection((byte) (1 == videoUser.getCollection() ? 0 : 1));
                videoUser.setCollectionTime(LocalDateTime.now());
            }
        }

        baseMapper.update(videoUser, Wrappers.<ShortVideoUser>query()
                .eq("user_id", videoUser.getUserId())
                .eq("video_id", videoUser.getVideoId())
        );
    }

    /**
     * 用户点赞收藏短视频信息
     *
     * @param videoId                 短视频id
     * @param shortVideoEventTypeEnum {@link  ShortVideoEventTypeEnum}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void userLikeOrCollection(String videoId, ShortVideoEventTypeEnum shortVideoEventTypeEnum) {
        QueryWrapper<ShortVideoUser> wrapper = Wrappers.<ShortVideoUser>query()
                .eq("user_id", SecurityUtils.getUserId())
                .eq("video_id", videoId);

        ShortVideoUser videoUser = baseMapper.selectOne(wrapper);

        if (null == videoUser) {
            save(videoId, SecurityUtils.getUserId(), shortVideoEventTypeEnum);
        } else {
            update(videoUser, shortVideoEventTypeEnum);
        }

        //添加监听时间
        setEvent(videoId, videoUser, shortVideoEventTypeEnum);
    }

    /**
     * 短视频点赞/收藏次数操作
     *
     * @param videoId                 短视频id
     * @param videoUser               {@link  ShortVideoUser}
     * @param shortVideoEventTypeEnum {@link  ShortVideoEventTypeEnum}
     */
    private void setEvent(String videoId, ShortVideoUser videoUser, ShortVideoEventTypeEnum shortVideoEventTypeEnum) {
        ShortVideoEventDTO dto = new ShortVideoEventDTO();
        dto.setId(videoId);
        dto.setEventTypeEnum(shortVideoEventTypeEnum);

        switch (shortVideoEventTypeEnum) {
            //点赞
            case LIKE -> dto.setCount((null == videoUser || videoUser.getLike() == 1) ? 1 : -1);
            //收藏
            case COLLECTION -> dto.setCount((null == videoUser || videoUser.getCollection() == 1) ? 1 : -1);
        }
        applicationContext.publishEvent(new ShortVideoAddEvent(dto));
    }

    /**
     * 查询用户收藏/点赞短视频信息
     *
     * @param videoUserDTO {@link AppVideoUserDTO}
     */
    @Override
    public Page<AppUserCollectionLikeVO> pageByApp(AppVideoUserDTO videoUserDTO) {

        Page<AppUserCollectionLikeVO> page = new Page<>(videoUserDTO.getPageNum(), videoUserDTO.getPageSize());
        page.setRecords(baseMapper.pageByApp(page, videoUserDTO));
        return page;
    }
}
